package com.hzc.springchan.service.impl;

import com.hzc.springchan.bean.exception.CException;
import com.hzc.springchan.bean.request.Request;
import com.hzc.springchan.bean.response.ListDataResponse;
import com.hzc.springchan.bean.response.MapDataResponse;
import com.hzc.springchan.bean.response.Response;
import com.hzc.springchan.config.resthelp.RequestConcurrent;
import com.hzc.springchan.enums.PrivError;
import com.hzc.springchan.service.IBusinessService;
import com.hzc.springchan.service.IRouteService;
import com.hzc.springchan.util.LogUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;

/**
 * 业务处理转发服务类
 * @author chen990627
 * @date 2022/10/18
 */
@Service
public class RouteServiceImpl implements IRouteService {

    static class BusinessReturn {

        static String MAP = "map";

        static String LIST = "list";

        static String NONE = "none";
    }

    @Autowired
    private RequestConcurrent requestConcurrent;

    @Autowired
    private Map<String, IBusinessService> businessServiceMap;

    @Override
    public Response routeService() {

        Request request = requestConcurrent.getCurrentRequest();

        IBusinessService businessService = businessServiceMap.get(request.getResourceName());
        if (businessService == null) {
            LogUtils.info(this, "businessService is null: {}", request.getResourceName());
            throw new CException(PrivError.UNDEFINED);
        }

        Type interType = businessService.getClass().getGenericInterfaces()[0];
        Type[] genericTypes = ((ParameterizedType) interType).getActualTypeArguments();
        String responseClass = genericTypes[1].getTypeName();
        String businessReturn = BusinessReturn.LIST;
        if (responseClass.equals(Response.class.getName())) {
            businessReturn = BusinessReturn.NONE;
        } else if (responseClass.equals(MapDataResponse.class.getName())) {
            businessReturn = BusinessReturn.MAP;
        }

        Response response = BusinessReturn.NONE.equals(businessReturn) ? Response.newSuccess() :
                BusinessReturn.MAP.equals(businessReturn) ? MapDataResponse.newSuccess(true) :
                        ListDataResponse.newSuccess(true);
        businessService.validate(request, responseTransform(response, businessReturn));
        if (!response.statusOk()) {
            LogUtils.info(this, "businessService validate fail");
            return responseTransform(response, businessReturn);
        }

        businessService.doBusiness(request, responseTransform(response, businessReturn));
        if (!response.statusOk()) {
            LogUtils.info(this, "businessService doBusiness fail");
            return responseTransform(response, businessReturn);
        }

        businessService.postBusiness(responseTransform(response, businessReturn));

        return responseTransform(response, businessReturn);
    }

    private Response responseTransform(Response response, String businessReturn) {
        return BusinessReturn.NONE.equals(businessReturn) ? response :
                BusinessReturn.MAP.equals(businessReturn) ? (MapDataResponse) response :
                        (ListDataResponse) response;
    }
}
